using System;
using System.Text;

namespace SourceConverter.Components
{
    public class ExtProperty
    {
        public string Name;
        public string Type;
        public string Scope;
        public string Access;
        public ExtDescription Description;

        public string ToExtSharp() {
            StringBuilder sb = new StringBuilder();
            if (SourceConverter.ShowDoc) sb.AppendLine(String.Format("        /// <summary>{0}</summary>", Description.GetDocComment()));
            sb.AppendLine("        [IntrinsicProperty]");
            sb.Append("        public ");
            if (Scope == "static") sb.Append("static ");
            sb.Append(ExtType.ParseType(Type) + " " + Name);
            sb.AppendLine(" { get { return " + ExtType.GetReturnValue(Type) + "; } set { } }");
            return sb.ToString();
        }

        public static void ParseProperty(string member, ref ExtClass ec) {
            /**
             * true if this component has been rendered. Read-only.
             */
            // rendered : false,
            string[] data = member.Split(SourceConverter.CRLFA, StringSplitOptions.RemoveEmptyEntries);
            ExtProperty ep = new ExtProperty();
            ep.Description = new ExtDescription();
            for (int i = 0; i < data.Length; i++) {
                string line = data[i];
                if (line.StartsWith("/**") && line.EndsWith("*/")) {
                    if (line.Contains("@type")) {
                        // /** blah blah @type Boolean */
                        // isOpera : isOpera,
                        line = line.Replace("/**", "").Replace("*/", "").Trim();
                        if (line.StartsWith("@type")) {
                            ep.Type = line.Replace("@type", "").Trim();
                        } else {
                            int index = line.IndexOf("@type");
                            ep.Description.Value += line.Substring(0, index).Trim();
                            ep.Type = line.Substring(index + "@type".Length).Trim();
                        }
                    } else {
                        // /** The normal browser event */
                        // browserEvent : null,
                        line = line.Replace("/**", "").Replace("*/", "").Trim();
                        ep.Type = "object";
                        ep.Description.Value = line;
                    }
                    break;
                }
                if (line.StartsWith("*/")) break;
                if (line.StartsWith("/**")) continue;
                if (line.StartsWith("@type")) {
                    ep.Type = line.Substring("@type".Length).Trim();
                    if (ep.Type.IndexOf(" ") > 0) ep.Type = ep.Type.Substring(0, ep.Type.IndexOf(" ")).Trim();
                } else if (line.StartsWith("@cfg") && !line.Contains("@hide")) {
                    // @cfg {String} emptyText The default text to display in an empty field (defaults to null).
                    string[] text = line.Split(" ".ToCharArray());
                    if (text.Length > 1) ep.Type = text[1]; // capture {String}
                    if (text.Length > 2) ep.Name = text[2]; // capture emptyText
                    if (text.Length > 3) {
                        // capture "The default text to display in an empty field (defaults to null)."
                        for (int j = 3; j < text.Length; j++) {
                            ep.Description.Value += text[j] + " ";
                        }
                        ep.Description.Value = ep.Description.Value.Trim();
                    }
                } else if (line.StartsWith("@static")) {
                    ep.Scope = "static";
                } else if (line.StartsWith("@property")) {
                    ep.Name = line.Substring("@property".Length).Trim();
                    if (ep.Name.Contains(".")) ep.Name = ep.Name.Substring(0, ep.Name.IndexOf(".")).Trim();

                    // hack for Ext.dd.DDProxy.dragElId
                    if (ec.Name == "DDProxy" && ep.Name == "Ext") ep.Name = "dragElId";

                    // hack for ColumnModel config property
                    //     @property {Array} config
                    if (ec.Name == "ColumnModel" && line.EndsWith("config")) {
                        ep.Name = "config";
                        ep.Type = "Array";
                    }
                } else if (line.StartsWith("@private") || line.StartsWith("@hide")) {
                    return; // ignore private & hidden members
                } else if (!line.Contains("@extproperty")) {
                    ep.Description.Value += line.Trim() + SourceConverter.CRLF;
                }
            }
            ep.Description.Value = ep.Description.Value.Trim(SourceConverter.CRLFA);

            if (String.IsNullOrEmpty(ep.Name)) {
                string[] lastLine = SourceConverter.ParseLastLine(member);
                if (lastLine.Length > 0) {
                    ep.Name = lastLine[0].Replace("this.", "").Replace("var", "").Trim();
                    ep.Name = ep.Name.Replace("'", "").Replace("\"", ""); // remove quotes
                    if (ep.Name.Contains(".")) {
                        string[] split = ep.Name.Split(".".ToCharArray());
                        ep.Name = split[split.Length - 1];
                    }
                } else {
                    return; // dont add if we cant parse the name
                }
            }

            if (String.IsNullOrEmpty(ep.Type)) {
                // try to guess the type based on the value on the last line
                string[] lastLine = SourceConverter.ParseLastLine(member);
                if (lastLine.Length > 1) {
                    string value = lastLine[1].Trim();
                    value.TrimEnd(',');
                    ep.Type = "Object";
                    if (value == "true" || value == "false") ep.Type = "boolean";
                    if (value.IndexOf("\"") >= 0) ep.Type = "String";
                    int d;
                    if (Int32.TryParse(value, out d)) ep.Type = "int";
                }
            }

            if (ExtType.IsStatic(ec, ep.Name)) ep.Scope = "static";

            if (ExtType.IsKeyword(ep.Name)) {
                string fqn = String.Format("{0}.{1}", ec.FullyQualifiedName, ep.Name);
                SourceConverter.RenamedProperties.Add(fqn, fqn + "_");
                ep.Name += "_";
            }

            // Ext.BasicForm bug
            if (ep.Name == "fileUpload.") ep.Name = "fileUpload";
            if (ep.Name == "store" && ec.Name == "ComboBox") ep.Type = "Ext.data.Store";
            // bad syntax in Ext.grid.GridPanel
            if (ep.Name.StartsWith("<p>")) ep.Name = ep.Name.Substring(3);

            ec.Properties.AddProperty(ep);
        }
    }
}
